package com.xhb.ui.component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.teamdev.jxbrowser.view.swing.BrowserView;
import com.xhb.biz.po.History;
import com.xhb.biz.service.ConfigService;
import com.xhb.biz.service.HistoryService;
import lombok.Data;
import org.noear.solon.Solon;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Date;
import java.util.List;
import java.util.regex.Pattern;


/**
 * 圆角输入框
 */
@Data
public class RoundJtextField extends JTextField implements FocusListener {

    private Shape shape;

    /**
     * 上一次键盘按下时间
     */
    public static Date keyDate;

    private BrowserView browserView;

    /**
     * URL 正则表达式
     */
    public static final String URL_PATTERN = "((http|https|ftp)://)?((((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]?\\d)\\.){3}((25[0-5])|(2[0-4]\\d)|(1\\d{2})|([1-9]?\\d)))|(([\\w-]+\\.)+(net|com|org|gov|edu|mil|info|travel|pro|museum|biz|[a-z]{2})))(/[\\w\\-~#]+)*(/[\\w-]+\\.[\\w]{2,4})?([\\?=&%_]?[\\w-]+)*";

    /**
     * IP + PORT 类型的网址正则表达式
     */
    public static final String IP_PORT_PATTERN = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";

    /**
     * 百度搜索的 URL
     */
    public static final String BAI_DU_SEARCH_URL = "baidu.com/s?wd=";

    public RoundJtextField() {
        setOpaque(false); // As suggested by @AVD in comment.
    }

    public RoundJtextField(String title, BrowserView browserView) {
        super(title);
        this.browserView = browserView;
        setOpaque(false); // As suggested by @AVD in comment.
        this.addFocusListener(this);
        setupAutoComplete(this);
    }

    @Override
    public void setBounds(int x, int y, int width, int height) {
        // TODO Auto-generated method stub
        super.setBounds(x, y, width, height);
    }

    protected void paintComponent(Graphics g) {
        g.setColor(getBackground());
        g.fillRoundRect(0, 0, getWidth() - 2, getHeight() - 2, 12, 12);
        super.paintComponent(g);
    }

    protected void paintBorder(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        //圆角抗锯齿
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
//		g2d.setColor(new Color(221,221,221));

        g2d.drawRoundRect(0, 0, getWidth() - 2, getHeight() - 2, 12, 12);
    }

    @Override
    public void focusGained(FocusEvent e) {
        this.selectAll();
    }

    @Override
    public void focusLost(FocusEvent e) {

    }

    @Override
    public void setText(String text) {
        if (text != null && text.contains("(")) {
            text = text.substring(0, text.indexOf("("));
        }
        super.setText(text);
    }

    public void loadNewUrl(String url) {
        this.setText(url);
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                String newUrl = searchText((getText()));
                newUrl = newUrl.replace("https://", "").replace("http://", "");
                browserView.getBrowser().
                        navigation().
                        loadUrl(newUrl);
            }
        });
    }

    /**
     * 判断如果输入的不是网址就换成百度搜索
     *
     * @param url
     */
    private String searchText(String url) {
        // 如果是自己的服务地址 在后面拼上 token
        String userIndexUrl = Solon.cfg().get("easy-borwser.default-index");
        if (url.contains(userIndexUrl)) {
            return Solon.context().getBean(ConfigService.class).getUserIndexUrl(userIndexUrl);
        }
        Pattern urlPattern = Pattern.compile(URL_PATTERN);
        Pattern ipReportPattern = Pattern.compile(IP_PORT_PATTERN);
        if (urlPattern.matcher(url).find() || ipReportPattern.matcher(url).find()) {
            return url;
        }
        return BAI_DU_SEARCH_URL + url;
    }


    /**
     * 自动根据历史补齐输入内容
     *
     * @param txtInput
     */
    public static void setupAutoComplete(final RoundJtextField txtInput) {
        final DefaultComboBoxModel model = new DefaultComboBoxModel();
        final JComboBox cbInput = new JComboBox(model) {
            public Dimension getPreferredSize() {
                return new Dimension(super.getPreferredSize().width, 0);
            }
        };
        setAdjusting(cbInput, false);
        cbInput.setSelectedItem(null);
        // 处理上下移动
        txtInput.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                RoundJtextField.keyDate = new Date();
                setAdjusting(cbInput, true);
                if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                    if (cbInput.isPopupVisible()) {
                        e.setKeyCode(KeyEvent.VK_ENTER);
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN) {
                    e.setSource(cbInput);
                    cbInput.dispatchEvent(e);
                    //回车加载新页面
                    if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                        if (cbInput.getSelectedItem() != null) {
                            txtInput.loadNewUrl(cbInput.getSelectedItem().toString());
                        } else {
                            txtInput.loadNewUrl(txtInput.getText());
                        }
                        cbInput.setPopupVisible(false);
                    }
                }
                if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
                    cbInput.setPopupVisible(false);
                }
                setAdjusting(cbInput, false);
            }
        });
        //内容有变动自动去db查询历史自动补全
        txtInput.getDocument().addDocumentListener(new DocumentListener() {
            public void insertUpdate(DocumentEvent e) {
                updateList();
            }

            public void removeUpdate(DocumentEvent e) {
                updateList();
            }

            public void changedUpdate(DocumentEvent e) {
                updateList();
            }

            private void updateList() {
                if (RoundJtextField.keyDate == null || (new Date().getTime() - RoundJtextField.keyDate.getTime() > 10)) {
                    return;
                }
                setAdjusting(cbInput, true);
                model.removeAllElements();
                String input = txtInput.getText();
                HistoryService historyService = Solon.context().getBean(HistoryService.class);
                if (!StringUtils.isBlank(input)) {
                    List<History> histories = historyService.list(new QueryWrapper<History>().select("DISTINCT title,url").like("url", input)
                            .orderByAsc("url_length").last(" limit 0,5"));
                    for (History history : histories) {
                        model.addElement(history.getUrl() + "(" + history.getTitle() + ")");
                    }
                }
                cbInput.setPopupVisible(model.getSize() > 0);
                setAdjusting(cbInput, false);
            }
        });
        txtInput.setLayout(new BorderLayout());
        txtInput.add(cbInput, BorderLayout.SOUTH);
    }

    private static void setAdjusting(JComboBox cbInput, boolean adjusting) {
        cbInput.putClientProperty("is_adjusting", adjusting);
    }

    private static boolean isAdjusting(JComboBox cbInput) {
        if (cbInput.getClientProperty("is_adjusting") instanceof Boolean) {
            return (Boolean) cbInput.getClientProperty("is_adjusting");
        }
        return false;
    }

}